/*******************************************************************************************
 *      @name   getweather.c
 *      @brief  这是在linux系统下的使用HTTP协议对心知天气服务器的天气实况的API接口进行天气请求
 *      @date   2025/02/26
 *      @author cecelmx@126.com 
 *      @note
 *              1.HTTP协议是基于请求/响应模式，而且HTTP服务有独立的端口号，HTTP服务的端口号是80
 *              2.心知天气服务器提供的API接口地址
 *               /v3/weather/now.json?key=your_api_key&location=beijing&language=en&unit=c
 * 
 *              3.心知天气最好是使用gethostbyname来进行域名的解析，得到服务器地址116.62.81.138
 * 
 *              4.心知天气返回的响应体是JSON格式，并且需要把APIKEY更为自己的密钥
 * 
 *      @version  xx.xx.xx   主版本号.次版本号.修正版本号
 * 
 *      CopyRight (c)   2024-2025   Your Name     All Right Reserved
 * 
 * ****************************************************************************************/

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <netdb.h>

//缓冲区大小
#define  BUFSIZE    1024

//心知天气API的密钥，需要修改为自己的密钥
#define  API_KEY   "S5jYTIuliBSEQmhkX"  

//HTTP服务的端口
#define  HTTP_PORT  80

//聚合API的URL
#define SERVER_URL  "/v3/weather/now.json"

//聚合API的IP
#define SERVER_IP   "116.62.81.138"

//聚合API的域名
#define SERVER_DOMAIN "api.seniverse.com"

int main(int argc,char **argv)
{
    char recvbuf[BUFSIZE] ={0}; //存储响应内容
    char request[BUFSIZE] ={0}; //存储请求内容

    //1.创建TCP套接字,HTTP协议是基于TCP协议实现的
    int tcp_socket = socket(AF_INET, SOCK_STREAM, 0); 
    if(-1 == tcp_socket)
    {
        fprintf(stderr,"create tcp socket error,%s\n",strerror(errno));
        exit(-1);
    }
    
    //2.向心知天气API的服务器发起连接请求
    struct sockaddr_in dest ={0};                           //IPv4地址格式的实例
    dest.sin_family = AF_INET;                              //IPv4协议族
    dest.sin_port   = htons(HTTP_PORT);                     //目标端口，需要转换为网络字节序
    dest.sin_addr.s_addr = inet_addr(SERVER_IP);            //目标地址，需要转换为网络字节序

    if(-1 == connect(tcp_socket,(struct sockaddr *)&dest,sizeof(dest)))
    {
        fprintf(stderr,"connect error,%s\n",strerror(errno));
        exit(-2);
    }

    printf("connect ok\n");

    for(;;)
    {
        //3.连接成功后，可以向服务器发起请求，需要构造请求内容
        char local[64] = {0};
        memset(request,0,BUFSIZE);     //清空接收缓冲区
        printf("请输入城市名称(拼音，例如Beijing):");
        scanf("%s",local);

        sprintf(request,"GET %s?key=%s&location=%s&language=en&unit=c HTTP/1.1\r\n"
                        "Host: %s\r\n"
                        "\r\n",
                        SERVER_URL,API_KEY,local,SERVER_DOMAIN);
        //4.发送请求
        send(tcp_socket,request,strlen(request),0); //向聚合API服务器发送请求
        printf("send ok\n");    
        
        //5.等待心知天气API的响应内容  先返回响应头部,再返回响应Body
        sleep(5);

        recv(tcp_socket,recvbuf,sizeof(recvbuf),0); //读取数据，默认会阻塞
        printf("%s\n",recvbuf);
        memset(recvbuf,0,BUFSIZE);     //清空接收缓冲区
        
       
    }
    
    
    return 0;
}

